#ifdef ARCTIC
#if (FEATURE_MODE == 0)
/**
 @file sys_at_ptp.c

 @author  Copyright (C) 2020 Centec Networks Inc.  All rights reserved.

 @date 2021-04-20

 @version v1.0

*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "sal.h"
#include "ctc_error.h"
#include "ctc_debug.h"
#include "ctc_crc.h"
#include "ctc_ptp.h"

#include "sys_usw_common.h"
#include "sys_usw_register.h"
#include "sys_usw_ptp.h"
#include "sys_usw_eunit.h"
#include "drv_api.h"
#include "sys_usw_interrupt.h"



/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/
#define SYS_PTP_CLOCK_ID_OFFSET 4
#define SYS_PTP_MAX_DURE_CNT 0xFFFF
#define SYS_PTP_FRACNS_BITS 2
#define SYS_PTP_CLOCK_ID_OFFSET 4
#define SYS_PTP_SUB_NS_THRD_IN_PKT 65536
#define SYS_PTP_MAX_VERSION_ID 3
#define SYS_PTP_SYNC_INTF_HW_MODE_BIT  31
#define SYS_PTP_HATA_TX_TS_FIFO_INTERRUPT_BIT_LEN 20
#define SYS_PTP_SFB_BIT_TIME 32
#define SYS_PTP_PM_BIT_TIME 1024
#define SYS_PTP_BIT_TIME_MUL 1000
#define SYS_PTP_DEFFAULT_DRIFT_COUNT 100000
#define SYS_PTP_MAC_NUM_PER_MCMAC 8
#define SYS_PTP_MAC_NUM_PER_CORE 160

enum sys_ptp_ts_out_offset_e
{
    SYS_PTP_TS_OUT_OFFSET_T1_T2_CNT0,
    SYS_PTP_TS_OUT_OFFSET_TS1 = 1,
    SYS_PTP_TS_OUT_OFFSET_TS2 = 3, 
    SYS_PTP_TS_OUT_OFFSET_CF_SYNC = 5,
    SYS_PTP_TS_OUT_OFFSET_T1_T2_CNT1 = 7,
    SYS_PTP_TS_OUT_OFFSET_T3_T4_CNT0 = 8,
    SYS_PTP_TS_OUT_OFFSET_TS3 = 9,
    SYS_PTP_TS_OUT_OFFSET_TS4 = 11, 
    SYS_PTP_TS_OUT_OFFSET_CF_REQ = 13,
    SYS_PTP_TS_OUT_OFFSET_T3_T4_CNT1 = 15
};
typedef enum sys_ptp_ts_out_offset_e sys_ptp_ts_out_offset_t;



struct sys_ptp_ts_s
{
    uint16 sec_msb;
    uint8 is_negative;
    uint32 sec_lsb;
    uint32 ns;
};
typedef struct sys_ptp_ts_s sys_ptp_ts_t;

struct sys_ptp_cf_s
{
    uint32 lsb;
    uint32 msb;
};
typedef struct sys_ptp_cf_s sys_ptp_cf_t;

extern uint8
sys_at_eunit_get_pp_id_by_eunit_id(uint8 lchip, uint8 eunit_id);
extern sys_ptp_master_t* p_usw_ptp_master[CTC_MAX_LOCAL_CHIP_NUM_PP];

#define SYS_AT_PTP_MASK_DISABLE_MAC(bmp) \
if (index >= SYS_PTP_TS_RC_MAC && index < SYS_PTP_TS_RC_OAM && !((1 << ((index - SYS_PTP_TS_RC_MAC) >> 2))&bmp)) \
{ \
    continue; \
}

STATIC int32 
_sys_at_ptp_get_delay(uint32 lantency,uint32 asymmetry_delay,uint8* negtive)
{
    uint32 result=0;
    if (*negtive)
    {
        if (asymmetry_delay > lantency)
        {
            result =  asymmetry_delay - lantency;
        }
        else
        {
            result = lantency - asymmetry_delay ;
            *negtive = 0;
        }
    }
    else
    {
        result = lantency + asymmetry_delay ;
    }
    return result;
}


STATIC int32 
_sys_at_ptp_get_top_ts_rc_id(uint8 domain_id)
{
    uint8 tsrc_id = 0;
    tsrc_id = domain_id? SYS_PTP_TS_RC_TOP + 2 : SYS_PTP_TS_RC_TOP;
    return tsrc_id;
}

STATIC int32 
_sys_at_ptp_get_ts_rtc_id(uint8 domain_id)
{
    uint8 tsrc_id = 0;
    tsrc_id = domain_id? SYS_PTP_RTC_2 : SYS_PTP_RTC_0;
    return tsrc_id;
}


int32 sys_at_ptp_set_sync_of_tod_input_select(uint8 lchip, uint32 value)
{
    uint32 cmd_sync = 0;
    uint32 cmd_tod = 0 ;
    uint32 field_sync_value = 0;
    uint32 field_tod_value = 0;
    
    cmd_sync = DRV_IOW(TsSyncIntfCfg_t, TsSyncIntfCfg_captureTsEn_f);
    cmd_tod = DRV_IOW(TsEngineTodCfg_t, TsEngineTodCfg_todTsCaptureEn_f);


    switch (value)
    {
    case CTC_PTP_INTF_SELECT_NONE:
        {
            field_sync_value = 0;
            field_tod_value = 0;
            break;
        }
    case CTC_PTP_INTF_SELECT_SYNC:
        {
            field_tod_value = 0;
            field_sync_value = 1;
            break;
        }
    case CTC_PTP_INTF_SELECT_TOD:
        {
            field_sync_value = 0;
            field_tod_value = 1;
            break;
        }
    default:
        {
            return CTC_E_INVALID_PARAM;
        }
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd_sync, &field_sync_value));
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 1, cmd_sync, &field_sync_value));
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd_tod, &field_tod_value));
    }

    p_usw_ptp_master[lchip]->intf_selected = value;

    return CTC_E_NONE;
}

int32
_sys_at_ptp_session_param_check(uint8 lchip, ctc_ptp_session_t* ptp_session)
{
    uint8 index = 0;
    uint8 domain_id = 0;
    uint8 gchip = 0;
    
    CTC_MAX_VALUE_CHECK(ptp_session->domain_id, MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID));
    CTC_MAX_VALUE_CHECK(ptp_session->default_info.two_step_flag, 1);
    CTC_MAX_VALUE_CHECK(ptp_session->port_info.version_id, SYS_PTP_MAX_VERSION_ID);
    gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(ptp_session->gport);
    if (!sys_usw_chip_is_local(lchip, gchip))
    {
        return CTC_E_INVALID_CHIP_ID;
    }
    CTC_MIN_VALUE_CHECK(SYS_GPORT_IS_NETWORK_PORT(ptp_session->gport), 1);
    
    CTC_MAX_VALUE_CHECK(ptp_session->port_info.sync_interval, (int8)MCHIP_CAP(SYS_CAP_PTP_MAX_INTERVAL));
    CTC_MIN_VALUE_CHECK(ptp_session->port_info.sync_interval, (int8)MCHIP_CAP(SYS_CAP_PTP_MIN_INTERVAL));

    CTC_MAX_VALUE_CHECK(ptp_session->port_info.delay_req_interval, (int8)MCHIP_CAP(SYS_CAP_PTP_MAX_INTERVAL));
    CTC_MIN_VALUE_CHECK(ptp_session->port_info.delay_req_interval, (int8)MCHIP_CAP(SYS_CAP_PTP_MIN_INTERVAL));

    domain_id = MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID) - ptp_session->domain_id;
    
    for (index = 0; index <= MCHIP_CAP(SYS_CAP_PTP_MAX_SESSION_ID); index++)
    {
        if (CTC_IS_BIT_SET(p_usw_ptp_master[lchip]->session_en_bmp[domain_id], index)
            && ptp_session->gport == p_usw_ptp_master[lchip]->session[domain_id * SYS_PTP_SESSION_NUM_PER_DOMAIN + index].gport)
        {
            return CTC_E_EXIST;
        }
    }    

    return CTC_E_NONE;
}



#define _________API_________


int32 sys_at_ptp_event_cb(uint8 gchip, void* data)
{
    return CTC_E_NONE;
}


#if defined E_UNIT && (FEATURE_MODE == 0)
int32 
sys_at_ptp_isr(uint8 lchip, uint8 isr_type, void* p_data)
{
    uint8 domain_id = 0;
    uint8 gchip =0;
    uint32 ptp_ts_out[20]={0};
    CTC_INTERRUPT_EVENT_FUNC ptp_cb = NULL;
    ctc_ptp_slave_rx_ts_t rx_ts;
    sys_usw_eunit_isr_data_t* isr_data = (sys_usw_eunit_isr_data_t*)p_data;
    sal_memset(&rx_ts,0,sizeof(ctc_ptp_slave_rx_ts_t));
    domain_id = isr_data->irq_id == SYS_EUNIT_ISR_PTP_0? MCHIP_CAP(SYS_CAP_PTP_DOMAIN_0) : MCHIP_CAP(SYS_CAP_PTP_DOMAIN_1);
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
    CTC_ERROR_RETURN(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_SLAVE_TS_READY, &ptp_cb));
    if (!ptp_cb)
    {
        return CTC_E_NOT_INIT;
    }
    
    /*1. Read DB from eCPU*/
   
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->read_data)
    {
        CTC_ERROR_RETURN(MCHIP_EUNIT(lchip)->read_data(lchip, domain_id? SYS_EUNIT_CFG_PTP_DOMAIN_1 : SYS_EUNIT_CFG_PTP_DOMAIN_0, ptp_ts_out, sizeof(ptp_ts_out)));
    }
    PTP_LOCK;

    /*judge data valid and cb to usr*/
    if (ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_T1_T2_CNT0] == ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_T1_T2_CNT1] \
        && p_usw_ptp_master[lchip]->t1_t2_count != ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_T1_T2_CNT0])
    {
        rx_ts.domain_id = domain_id;
        rx_ts.rx_ts0.seconds = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_TS1+1];
        rx_ts.rx_ts1.seconds = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_TS2+1];
        rx_ts.rx_ts0.nanoseconds = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_TS1];
        rx_ts.rx_ts1.nanoseconds = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_TS2];
        rx_ts.cf[0] = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_CF_SYNC];
        rx_ts.cf[1] = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_CF_SYNC+1];
        rx_ts.is_t1_t2 =1;
        p_usw_ptp_master[lchip]->t1_t2_count = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_T1_T2_CNT0];
        PTP_UNLOCK;
        ptp_cb(gchip, &rx_ts);
        PTP_LOCK;
    }
    
    sal_memset(&rx_ts,0,sizeof(ctc_ptp_slave_rx_ts_t));

    if (ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_T3_T4_CNT0] == ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_T3_T4_CNT1] \
        && p_usw_ptp_master[lchip]->t3_t4_count != ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_T3_T4_CNT0])
    {
        rx_ts.domain_id = domain_id;
        rx_ts.rx_ts0.seconds = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_TS3+1];
        rx_ts.rx_ts1.seconds = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_TS4+1];
        rx_ts.rx_ts0.nanoseconds = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_TS3];
        rx_ts.rx_ts1.nanoseconds = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_TS4];
        rx_ts.cf[0] = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_CF_REQ];
        rx_ts.cf[1] = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_CF_REQ+1];
        rx_ts.is_t1_t2 =0;
        p_usw_ptp_master[lchip]->t3_t4_count = ptp_ts_out[SYS_PTP_TS_OUT_OFFSET_T3_T4_CNT0];
        PTP_UNLOCK;
        ptp_cb(gchip, &rx_ts);
        PTP_LOCK;
    }

    PTP_UNLOCK;
    return CTC_E_NONE;

}
#endif


int32
sys_at_ptp_isr_tx_ts_capture(uint8 lchip, uint32 intr, void* p_data)
{
    ds_t hata_tx_info;
    ctc_ptp_ts_cache_t* cache =(ctc_ptp_ts_cache_t*)p_data ;
    ctc_ptp_time_t fifo_ts;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    CTC_INTERRUPT_EVENT_FUNC cb = NULL;
    uint64 tmp_hatac_ns = 0;
    uint32 table_id = 0;
    uint32 cmd = 0;
    uint32 pm_cnt = 0;
    uint32 hatac_ns = 0;
    uint32 bit_time =0;
    int32 ret = CTC_E_NONE;
    uint8 mac_id = 0;
    uint8 index = 0;
    uint8 fifo_valid = 0;
    uint8 sfb_id = 0;
    uint8 gchip = 0;
    uint8 pkt_num = 0;

    sal_memset(&hata_tx_info, 0, sizeof(hata_tx_info));
    sal_memset(&fifo_ts, 0, sizeof(fifo_ts));

    sys_usw_get_gchip_id(lchip, &gchip);
    index = intr - SYS_INTR_FUNC_PTP_TX_TS_FIFO_0_START;

    if(index < SYS_PTP_HATA_TX_TS_FIFO_INTERRUPT_BIT_LEN)
    {
        table_id = McHataTxCpuFifo0Pop_t;
    }
    else
    {
        table_id = McHataTxCpuFifo1Pop_t;
        index -= SYS_PTP_HATA_TX_TS_FIFO_INTERRUPT_BIT_LEN;
    }
    /*find interrupt from which McHata, handle all interrupt*/

    /*pop fifo*/
    cmd = DRV_IOR(table_id, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hata_tx_info));

    fifo_valid = hata_tx_info[3]>>31;

    while(fifo_valid)
    {
        for(pkt_num = 0; pkt_num <= 1 ; pkt_num++)
        {
            if (pkt_num == 0 && !(hata_tx_info[2]&0x1))/*num=0,check pkt0 enable*/
            {
                continue;
            }
            else if(pkt_num == 1 && !((hata_tx_info[2] >> 1)&0x1))/*num=1,check pkt1 enable*/
            {
                continue;
            }
            cache->entry[cache->entry_count].type = CTC_PTP_CAPTURED_TYPE_TX;
            /*get lport by mac_id*/
            mac_id = ((hata_tx_info[3] >> 16) & 0x7) + (index << 3);/*index * Mac_per_Hata*/
            if(lchip != SYS_PP_BASE(lchip))
            {
                mac_id += SYS_PTP_MAC_NUM_PER_CORE;
            }
            cache->entry[cache->entry_count].u.lport = sys_usw_port_api_get_lport_with_mac(lchip, mac_id);
            fifo_ts.seconds = hata_tx_info[1];
            fifo_ts.nanoseconds = hata_tx_info[0] >> 2;
            fifo_ts.nano_nanoseconds = ((hata_tx_info[0]&0x3)*SYS_PTP_SUB_NS_THRD_IN_PKT) >> 2;
            pm_cnt = (hata_tx_info[2] >> 26) | ((hata_tx_info[3]&0xFFF)<<6);

            if(pkt_num == 0)
            {
                cache->entry[cache->entry_count].msg_type = (hata_tx_info[2] >> 2)&0x3;
                cache->entry[cache->entry_count].seq_id = (hata_tx_info[2] >> 4)&0xF;
                sfb_id = (hata_tx_info[2] >> 14)&0x3F;
            }
            else
            {
                cache->entry[cache->entry_count].msg_type = (hata_tx_info[2] >> 8)&0x3;
                cache->entry[cache->entry_count].seq_id = (hata_tx_info[2] >> 10)&0xF;
                sfb_id = (hata_tx_info[2] >> 20)&0x3F;
            }

            if (((hata_tx_info[3] >> 19)&0x1))/*hata enable , need adjust*/
            {
                dmps_port_info.gport = CTC_MAP_LPORT_TO_GPORT(gchip, cache->entry[cache->entry_count].u.lport);
                CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_VALUE, &bit_time));/*return value is Mbps*/
                tmp_hatac_ns = (uint64)((uint64)1000*1000)*(sfb_id * SYS_PTP_SFB_BIT_TIME + pm_cnt * SYS_PTP_PM_BIT_TIME)/bit_time;
                hatac_ns = tmp_hatac_ns / SYS_PTP_BIT_TIME_MUL;

                /*Get adjust ns & frac_ns from Hata*/
                if (fifo_ts.nanoseconds + hatac_ns >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
                {
                    fifo_ts.nanoseconds = fifo_ts.nanoseconds + hatac_ns - MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
                    fifo_ts.seconds ++;
                }
                else
                {
                    fifo_ts.nanoseconds += hatac_ns;
                }
                /*adjust nano_ns*/
                fifo_ts.nano_nanoseconds = (uint32)(tmp_hatac_ns % SYS_PTP_BIT_TIME_MUL)*SYS_PTP_SUB_NS_THRD_IN_PKT / SYS_PTP_BIT_TIME_MUL;
            }

            cache->entry[cache->entry_count].ts.seconds = fifo_ts.seconds;
            cache->entry[cache->entry_count].ts.nanoseconds = fifo_ts.nanoseconds;
            cache->entry[cache->entry_count].ts.nano_nanoseconds = fifo_ts.nano_nanoseconds;

            SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "entry:%d, type:%d, port:%d, seq_id:%d, msg_type:%d, s:%d, ns:%d origin sec: %d, origin ns: %d, pm: %d sfb: %d hata latency:%d\n",
                                                    cache->entry_count,
                                                    cache->entry[cache->entry_count].type,
                                                    cache->entry[cache->entry_count].u.lport,
                                                    cache->entry[cache->entry_count].seq_id,
                                                    cache->entry[cache->entry_count].msg_type,
                                                    cache->entry[cache->entry_count].ts.seconds,
                                                    cache->entry[cache->entry_count].ts.nanoseconds,
                                                    hata_tx_info[1],hata_tx_info[0] >> 2,pm_cnt,sfb_id,hatac_ns);
            cache->entry_count++;
        }
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &hata_tx_info));
        fifo_valid = hata_tx_info[3] >> 31;
    }

    /* call Users callback*/
    CTC_ERROR_DUMP(sys_usw_interrupt_get_event_cb(lchip, CTC_EVENT_PTP_TX_TS_CAPUTRE, &cb));
    if (cb)
    {
        (void)cb(gchip, cache);
    }

    return ret;
}


int32 sys_at_ptp_set_clock_drift(uint8 lchip, void* drift)
{
    ds_t ds;
    uint64 drift_frq = 0;
    uint64 act_freq = 0;
    uint32 cmd = 0;
    uint32 mc_mac_valid[2] = {0};
    uint32 drift_quanta[2]={0};
    uint16 ts_top_rc = 0;
    uint8 mask =0x3E;/*11 1110, mask except TsRcQuantaDriftShadow*/
    uint8 index = 0;
    uint8 rtc_id =0;
    uint8 pp_id = 0;
    ctc_ptp_time_t* p_drift = NULL;

	sys_usw_port_api_get_mac_group_valid(lchip,0, &mc_mac_valid[0]);
    if (PP_NUM_PER_CORE != SYS_PP_NUM(lchip))
    {
        sys_usw_port_api_get_mac_group_valid(lchip, 1, &mc_mac_valid[1]);
    }

    p_drift = (ctc_ptp_time_t*)drift;
    ts_top_rc = _sys_at_ptp_get_top_ts_rc_id(p_drift->domain_id);
    rtc_id = _sys_at_ptp_get_ts_rtc_id(p_drift->domain_id);

    /*Cal drift_frq and new qunata , drift is based on MCHIP_CAP(SYS_CAP_PTP_RC_QUANTA) and never appended*/
    act_freq = p_drift->is_negative?(MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) + p_drift->nanoseconds) \
    :(MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - p_drift->nanoseconds);
    drift_frq = (uint64)(act_freq * ((uint64)MCHIP_CAP(SYS_CAP_PTP_RC_QUANTA)<<34) / (uint64)MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) );

    drift_quanta[0] = drift_frq&0xFFFFFFFF;
    drift_quanta[1] = drift_frq>>32;
    SetTsRcQuantaDriftShadow(A, quantaDriftShadow_f, &ds, drift_quanta);

    for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
    {
        if (pp_id != 0 && pp_id != PP_NUM_PER_CORE)
        {
            continue;
        }

        /*set mask for p_drift->domain*/
        for (index = 0; index < SYS_PTP_TS_RC_MAX; index++)
        {
            if (sys_usw_ptp_get_rtc_id(index) != rtc_id)
            {
                continue;
            }

            if (pp_id == 0)
            {
                SYS_AT_PTP_MASK_DISABLE_MAC(mc_mac_valid[0]);
            }
            else
            {
                SYS_AT_PTP_MASK_DISABLE_MAC(mc_mac_valid[1]);
            }

            cmd = DRV_IOR(TsRcCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &ds));
            SetTsRcCtl(V, syncModeMask_f, &ds,mask);
            cmd = DRV_IOW(TsRcCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &ds));
        }

        /*Reload quanta by quantaDriftShadow*/
        for (index = 0; index < SYS_PTP_TS_RC_MAX; index++)
        {
            if (sys_usw_ptp_get_rtc_id(index) != rtc_id)
            {
                continue;
            }

            if (pp_id == 0)
            {
                SYS_AT_PTP_MASK_DISABLE_MAC(mc_mac_valid[0]);
            }
            else
            {
                SYS_AT_PTP_MASK_DISABLE_MAC(mc_mac_valid[1]);
            }

            cmd = DRV_IOW(TsRcQuantaDriftShadow_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &drift_quanta));
        }
    }

    /*trigger master load*/
    cmd = DRV_IOR(TsRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_top_rc , DRV_CMD_PP_EN(cmd), &ds));
    SetTsRcCtl(V, loadManualTrigger_f, &ds, 1);
    cmd = DRV_IOW(TsRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_top_rc , DRV_CMD_PP_EN(cmd), &ds));

    p_usw_ptp_master[lchip]->drift_nanoseconds = p_drift->is_negative << 31 | p_drift->nanoseconds;

    return CTC_E_NONE;
}


int32 sys_at_ptp_get_clock_drift(uint8 lchip, void* drift)
{
    ctc_ptp_time_t* p_drift = (ctc_ptp_time_t*)drift;
    p_drift->is_negative = (p_usw_ptp_master[lchip]->drift_nanoseconds >> 31) & 0x1;
    p_drift->seconds = 0;
    p_drift->nanoseconds = p_usw_ptp_master[lchip]->drift_nanoseconds & 0x7fffffff;
    p_drift->nano_nanoseconds = 0;

    return CTC_E_NONE;
}

int32 sys_at_ptp_adjust_clock_offset(uint8 lchip, void* p_offset)
{
    uint32 cmd = 0;
    ds_t ds;
    uint16 rtc_id = 0;
    uint8 mask = 0x3F;
    uint8 mask1 = 0x3F;
    uint8 pp_id = 0;
    uint32 mc_mac_valid[2] = {0};
    uint32 drift_dura[2] = {0};
    uint32 old_ts[2] = {0};
    uint32 new_ts[2] = {0};
    uint8 fine_tuning = 0;
    uint64 tmp_offset=0;
    uint64 tmp_ts=0;
    uint64 tmp_drift=0;
    uint32 tmp_value=0;
    uint8 ts_top_rc =0;
    uint8 index =0;
    uint32 tmp_ts_nns =0;
    uint32 tmp_offset_nns =0;
    uint32 dura_cnt=0;
    ctc_ptp_time_t* offset= (ctc_ptp_time_t*)p_offset;
    ts_top_rc = _sys_at_ptp_get_top_ts_rc_id(offset->domain_id);
    rtc_id = _sys_at_ptp_get_ts_rtc_id(offset->domain_id);
    fine_tuning = (offset->seconds || offset->nanoseconds > MCHIP_CAP(SYS_CAP_PTP_MIN_OFFSET_RELOAD))? 0 : 1;
    tmp_offset = (uint64)offset->seconds*MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) | offset->nanoseconds;
    tmp_offset_nns = offset->nano_nanoseconds;

	sys_usw_port_api_get_mac_group_valid(lchip,0, &mc_mac_valid[0]);
    if (PP_NUM_PER_CORE != SYS_PP_NUM(lchip))
    {
        sys_usw_port_api_get_mac_group_valid(lchip, 1, &mc_mac_valid[1]);
    }

    if (!fine_tuning)
    {
        /*Reload time by TsRcNsCntShadow & TsRcSecCntShadow*/
        CTC_BIT_UNSET(mask, SYS_PTP_SHADOW_NS_CNT);
        CTC_BIT_UNSET(mask, SYS_PTP_SHADOW_SEC_CNT);

    }
    else
    {
        /*if offset is negative, must check adjust_drift < 4(quanta)*/
        if(offset->adjust_count && offset->is_negative && (offset->nanoseconds / offset->adjust_count >= 1))
        {
            return CTC_E_INTR_INVALID_PARAM;
        }
        /*Fine tuning by TsRcQuantaDriftDuraShadow */
        CTC_BIT_UNSET(mask, SYS_PTP_SHADOW_DRIFT_DURA);
        CTC_BIT_UNSET(mask, SYS_PTP_SHADOW_DURA_CNT);
    }

    for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
    {
        if (pp_id != 0 && pp_id != PP_NUM_PER_CORE)
        {
            continue;
        }

        for (index = 0; index < SYS_PTP_TS_RC_MAX; index++)
        {

            if (sys_usw_ptp_get_rtc_id(index) != rtc_id)
            {
                continue;
            }

            if (pp_id == 0)
            {
                SYS_AT_PTP_MASK_DISABLE_MAC(mc_mac_valid[0]);
            }
            else
            {
                SYS_AT_PTP_MASK_DISABLE_MAC(mc_mac_valid[1]);
            }

            /*Trigger read old param*/
            cmd = DRV_IOR(TsRcCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &ds));
            SetTsRcCtl(V, syncModeMask_f, &ds, fine_tuning? CTC_BIT_UNSET(mask1, SYS_PTP_SHADOW_DRIFT) : CTC_BIT_UNSET(mask1, SYS_PTP_SHADOW_LOCAL_TS));
            cmd = DRV_IOW(TsRcCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &ds));
        }
    }

    cmd = DRV_IOR(TsRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_top_rc , DRV_CMD_PP_EN(cmd), &ds));
    SetTsRcCtl(V, captureManualTrigger_f, &ds, 1);
    cmd = DRV_IOW(TsRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_top_rc , DRV_CMD_PP_EN(cmd), &ds));

    for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
    {
        if (pp_id != 0 && pp_id != PP_NUM_PER_CORE)
        {
            continue;
        }

        for (index = 0; index < SYS_PTP_TS_RC_MAX; index++)
        {
            if (sys_usw_ptp_get_rtc_id(index) != rtc_id)
            {
                continue;
            }

            if (pp_id == 0)
            {
                SYS_AT_PTP_MASK_DISABLE_MAC(mc_mac_valid[0]);
            }
            else
            {
                SYS_AT_PTP_MASK_DISABLE_MAC(mc_mac_valid[1]);
            }

            /*set mask by offset->domain_id*/
            cmd = DRV_IOR(TsRcCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index ,  DRV_CMD_PP_EN(cmd), &ds));
            SetTsRcCtl(V, syncModeMask_f, &ds, mask);
            cmd = DRV_IOW(TsRcCtl_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index ,  DRV_CMD_PP_EN(cmd), &ds));

            if (!fine_tuning)
            {
                /*Reload time by TsRcNsCntShadow & TsRcSecCntShadow*/
                cmd = DRV_IOR(TsRcLocalTsShadow_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &ds));
                GetTsRcLocalTsShadow(A, localTsShadow_f, &ds, old_ts);
                tmp_ts = (uint64)old_ts[1]*MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) | (old_ts[0] >> SYS_PTP_FRACNS_BITS);
                tmp_ts_nns = (old_ts[0]&0x3)*MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) / 4;
                if (offset->is_negative)
                {
                    if (tmp_ts_nns >= tmp_offset_nns)
                    {
                        tmp_ts -= tmp_offset;
                        tmp_ts_nns -= tmp_offset_nns;
                    }
                    else
                    {
                        tmp_ts -= (tmp_offset + 1);
                        tmp_ts_nns += MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) - tmp_offset_nns;
                    }
                }
                else
                {
                    tmp_ts += tmp_offset;
                    tmp_ts_nns += tmp_offset_nns;
                    if (tmp_ts_nns >= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE))
                    {
                        tmp_ts++;
                        tmp_ts_nns -= MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);

                    }  
                }

                sal_memset(&ds, 0, sizeof(ds));
                tmp_value = tmp_ts / MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
                SetTsRcSecCntShadow(V, secCntShadow_f, &ds, tmp_value);
                cmd = DRV_IOW(TsRcSecCntShadow_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &ds));

                sal_memset(&ds, 0, sizeof(ds));
                new_ts[1] = (tmp_ts % MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) << SYS_PTP_FRACNS_BITS) | tmp_ts_nns*4 / MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE);
                SetTsRcNsCntShadow(A, nsCntShadow_f, &ds, new_ts);
                cmd = DRV_IOW(TsRcNsCntShadow_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &ds));
            }
            else
            {
                cmd = DRV_IOR(TsRcQuantaDriftShadow_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &ds));
                if(!offset->adjust_count)
                {
                    dura_cnt = SYS_PTP_DEFFAULT_DRIFT_COUNT;
                }
                else
                {
                    dura_cnt = offset->adjust_count;
                }
                /* caculate new quantaDrift*/
                tmp_drift = ((uint64)ds[1] << 32) | ds[0] ;
                if (offset->is_negative)
                {            
                    tmp_drift = tmp_drift - ((uint64)MCHIP_CAP(SYS_CAP_PTP_RC_QUANTA)<<34)*offset->nanoseconds / dura_cnt;
                }
                else
                {
                    tmp_drift = tmp_drift + ((uint64)MCHIP_CAP(SYS_CAP_PTP_RC_QUANTA)<<34)*offset->nanoseconds / dura_cnt;
                }
                drift_dura[0] =  tmp_drift&0xFFFFFFFF;
                drift_dura[1] =  tmp_drift >> 32;

                /*write TsRcQuantaDriftDuraShadow & TsRcDuraCntShadow*/
                cmd = DRV_IOW(TsRcQuantaDriftDuraShadow_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &drift_dura));

                cmd = DRV_IOW(TsRcDuraCntShadow_t, DRV_ENTRY_FLAG);
                CTC_ERROR_RETURN(DRV_IOCTL(lchip + pp_id, index , DRV_CMD_PP_EN(cmd), &dura_cnt));
            }
        }
    }

    cmd = DRV_IOR(TsRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_top_rc , DRV_CMD_PP_EN(cmd), &ds));
    SetTsRcCtl(V, loadManualTrigger_f, &ds, 1);
    cmd = DRV_IOW(TsRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_top_rc , DRV_CMD_PP_EN(cmd), &ds));

    return CTC_E_NONE;
}


int32 sys_at_ptp_set_sync_intf(uint8 lchip, void* config)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    TsSyncIntfCfg_m ptp_sync_intf_cfg;
    TsSyncClockHalfPeriod_m ptp_sync_intf_half_period;
    TsSyncPulseHalfPeriod_m ptp_sync_pluse_half_period;
    TsEngineTsCaptureFifoAdjRc_m ptp_captured_adj_frc;
    TsSyncIntfInputCode_m input_code;
    uint16 adj_frc_bitmap = 0;
    sys_intr_type_t type;
    sys_eunit_ptp_cfg_t ptp_cfg;
    ctc_ptp_sync_intf_cfg_t* p_config = (ctc_ptp_sync_intf_cfg_t*)config;
    uint32 mc_mac_valid[2] = {0};

	sys_usw_port_api_get_mac_group_valid(lchip,0, &mc_mac_valid[0]);
    if (PP_NUM_PER_CORE != SYS_PP_NUM(lchip))
    {
        sys_usw_port_api_get_mac_group_valid(lchip, 1, &mc_mac_valid[1]);
    }

    sal_memset(&type, 0, sizeof(type));
    type.intr = p_config->domain_id?SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY1:SYS_INTR_FUNC_PTP_SYNC_CODE_IN_RDY;
    type.sub_intr = INVG;
    CTC_ERROR_RETURN(sys_usw_interrupt_set_en(lchip, &type, p_config->hw_mode ? 0 : 1));

    /*set sync interface as input mode*/
    cmd = DRV_IOR(TsSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_config->domain_id, cmd, &ptp_sync_intf_cfg), ret , out);

    SetTsSyncIntfCfg(V, syncIntfMode_f, &ptp_sync_intf_cfg, 0);
    cmd = DRV_IOW(TsSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_config->domain_id, cmd, &ptp_sync_intf_cfg), ret, out);

    p_usw_ptp_master[lchip]->sync_mode[p_config->domain_id] = p_config->mode;
    /*set sync interface config*/
    SetTsSyncIntfCfg(V, syncIntfMode_f, &ptp_sync_intf_cfg, p_config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 1 : 0);
    SetTsSyncIntfCfg(V, lock_f, &ptp_sync_intf_cfg, p_config->lock ? 1 : 0);
    SetTsSyncIntfCfg(V, epoch_f, &ptp_sync_intf_cfg, p_config->epoch);
    SetTsSyncIntfCfg(V, accuracy_f, &ptp_sync_intf_cfg, p_config->accuracy);
    SetTsSyncIntfCfg(V, syncPulseIntrEn_f, &ptp_sync_intf_cfg,p_config->mode == CTC_PTP_INTF_MODE_1PPS_ONLY ? 1 : 0);
    SetTsSyncIntfCfg(V, ignoreSyncCodeInRdy_f, &ptp_sync_intf_cfg,p_config->mode == CTC_PTP_INTF_MODE_1PPS_ONLY ? 1 : 0);
    SetTsSyncIntfCfg(V, syncCodeOutEnable_f, &ptp_sync_intf_cfg, p_config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 1 : 0);
    SetTsSyncIntfCfg(V, syncPulseOutEnable_f, &ptp_sync_intf_cfg, p_config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 1 : 0);
    SetTsSyncIntfCfg(V, syncClockOutEnable_f, &ptp_sync_intf_cfg, p_config->mode == CTC_PTP_INTF_MODE_OUTPUT ? 1 : 0);
    SetTsSyncIntfCfg(V, captureTsEn_f, &ptp_sync_intf_cfg, 1);
    cmd = DRV_IOW(TsSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_config->domain_id, cmd, &ptp_sync_intf_cfg), ret, out);

    /*clear code ready for mode change*/
    sal_memset(&input_code, 0, sizeof(input_code));
    cmd = DRV_IOW(TsEngineSyncIntfInputCode_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &input_code));

    /*calculate syncClock half period and syncPulse period&duty*/
    sal_memset(&ptp_sync_intf_half_period, 0, sizeof(ptp_sync_intf_half_period));
    SetTsSyncClockHalfPeriod(V, syncClockHalfPeriod_f, &ptp_sync_intf_half_period, MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) / (p_config->sync_clock_hz * 2));
    cmd = DRV_IOW(TsSyncClockHalfPeriod_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_config->domain_id, cmd, &ptp_sync_intf_half_period), ret, out);

    sal_memset(&ptp_sync_pluse_half_period, 0, sizeof(ptp_sync_pluse_half_period));
    SetTsSyncPulseHalfPeriod(V, syncPulseHalfPeriod_f, &ptp_sync_pluse_half_period, p_config->sync_clock_hz / p_config->sync_pulse_hz);
    cmd = DRV_IOW(TsSyncPulseHalfPeriod_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_config->domain_id, cmd, &ptp_sync_pluse_half_period), ret, out);

    /*for input mode need clear first*/
    if (!p_config->mode)
    {
        sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
        cmd = DRV_IOR(TsEngineTsCaptureFifoAdjRc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_adj_frc), ret, out);

        adj_frc_bitmap = GetTsEngineTsCaptureFifoAdjRc(V, adjRcBitmap_f, &ptp_captured_adj_frc);
        while (adj_frc_bitmap) /*the FIFO is empty when the bitmap is 0*/
        {
            sal_memset(&ptp_captured_adj_frc, 0, sizeof(ptp_captured_adj_frc));
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ptp_captured_adj_frc), ret, out);
            adj_frc_bitmap = GetTsEngineTsCaptureFifoAdjRc(V, adjRcBitmap_f, &ptp_captured_adj_frc);
        }
    }

    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->set_cfg)
    {
        CTC_ERROR_GOTO(MCHIP_EUNIT(lchip)->get_cfg(lchip, p_config->domain_id? SYS_EUNIT_CFG_PTP_DOMAIN_1 : SYS_EUNIT_CFG_PTP_DOMAIN_0, (void*)&ptp_cfg),ret,out);
        ptp_cfg.set_syncIntf_prama = 1;
        ptp_cfg.syncIntf_cfg = p_config->hw_mode << SYS_PTP_SYNC_INTF_HW_MODE_BIT | p_config->drift_time;
        ptp_cfg.mc_mac_valid0 = mc_mac_valid[0];
        ptp_cfg.mc_mac_valid1 = mc_mac_valid[1];
        CTC_ERROR_GOTO(MCHIP_EUNIT(lchip)->set_cfg(lchip, p_config->domain_id? SYS_EUNIT_CFG_PTP_DOMAIN_1 : SYS_EUNIT_CFG_PTP_DOMAIN_0, (void*)&ptp_cfg),ret,out);
    }

    p_usw_ptp_master[lchip]->hw_mode = p_config->hw_mode;
    return CTC_E_NONE;

out:
    return ret;
}

int32 sys_at_ptp_get_sync_intf(uint8 lchip, void* config)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint32 half_period_ns = 0;
    uint32 sync_pulse_out_period = 0;
    TsSyncIntfCfg_m ptp_sync_intf_cfg;
    TsSyncClockHalfPeriod_m ptp_sync_intf_half_period;
    TsSyncPulseHalfPeriod_m sync_pulse_half_period;
    ctc_ptp_sync_intf_cfg_t* p_config = (ctc_ptp_sync_intf_cfg_t*)config;

    /*set sync interface config*/
    cmd = DRV_IOR(TsSyncIntfCfg_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_config->domain_id, cmd, &ptp_sync_intf_cfg), ret, out);

    cmd = DRV_IOR(TsSyncClockHalfPeriod_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_config->domain_id, cmd, &ptp_sync_intf_half_period), ret, out);

    half_period_ns = GetTsSyncClockHalfPeriod(V, syncClockHalfPeriod_f,&ptp_sync_intf_half_period);
    p_config->mode = p_usw_ptp_master[lchip]->sync_mode[p_config->domain_id];
    p_config->lock = GetTsSyncIntfCfg(V, lock_f, &ptp_sync_intf_cfg);
    p_config->epoch = GetTsSyncIntfCfg(V, epoch_f, &ptp_sync_intf_cfg);
    p_config->accuracy = GetTsSyncIntfCfg(V, accuracy_f, &ptp_sync_intf_cfg);

    cmd = DRV_IOR(TsSyncPulseHalfPeriod_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, p_config->domain_id, cmd, &sync_pulse_half_period), ret, out);
    sync_pulse_out_period = GetTsSyncPulseHalfPeriod(V, syncPulseHalfPeriod_f,&sync_pulse_half_period);


    if (0 == half_period_ns)
    {
        p_config->sync_clock_hz = 0;
    }
    else
    {
        p_config->sync_clock_hz = MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE) / (half_period_ns * 2);
    }

    if (0 == sync_pulse_out_period)
    {
        p_config->sync_pulse_hz = 0;
    }
    else
    {
        p_config->sync_pulse_hz = p_config->sync_clock_hz / sync_pulse_out_period;
    }

    return CTC_E_NONE;

out:
    return ret;
}

int32 sys_at_ptp_set_device_type(uint8 lchip, uint8 device_type)
{
    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    ds_t ptp_profile;
    uint8 index = 0;

    sal_memset(&ptp_profile, 0, sizeof(ds_t));
    cmd = DRV_IOW(DsPtpMsgProfile_t, DRV_ENTRY_FLAG);

    /*config device type*/
    switch (device_type)
    {
        case CTC_PTP_DEVICE_NONE:
        {
            for (index = 0; index < CTC_PTP_MSG_TYPE_MAX; index++)
            {
                 CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | index , cmd, &ptp_profile), ret, out);
            }
            break;
        }
        case CTC_PTP_DEVICE_OC:
        case CTC_PTP_DEVICE_BC:
        {
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*sync*/
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyIngressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_SYNC , cmd, &ptp_profile), ret, out);
            
            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*delay_req*/
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyEgressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_DELAY_REQ , cmd, &ptp_profile), ret, out);
            
            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*peer delay_req*/
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyEgressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, prevDiscardObeyException_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_PDELAY_REQ , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*peer delay_resp*/
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyIngressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, prevDiscardObeyException_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_PDELAY_RESP , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*follow_up*/
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_FOLLOW_UP , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*delay_resp*/
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_DELAY_RESP , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*peer delay_resp_follow_up*/
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, prevDiscardObeyException_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_PDELAY_RESP_FOLLOW_UP , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*announce*/
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_ANNOUNCE , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*signaling*/
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_SIGNAL , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*management*/
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_MANAGEMENT , cmd, &ptp_profile), ret, out);
            break;
        }
        case CTC_PTP_DEVICE_E2E_TC:
        {
            SetDsPtpMsgProfile(V, updateResidenceTime_f, &ptp_profile, 1); /*sync*/
            SetDsPtpMsgProfile(V, applyIngressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_SYNC , cmd, &ptp_profile), ret, out);
            
            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, updateResidenceTime_f, &ptp_profile, 1); /*delay_req*/
            SetDsPtpMsgProfile(V, isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyEgressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_DELAY_REQ , cmd, &ptp_profile), ret, out);
            
            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1); /*peer delay_req*/
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_PDELAY_REQ , cmd, &ptp_profile), ret, out);
            
            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1); /*peer delay_resp*/
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_PDELAY_RESP , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1); /*peer delay_resp_follow_up*/
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_PDELAY_RESP_FOLLOW_UP , cmd, &ptp_profile), ret, out);
            
            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_FOLLOW_UP , cmd, &ptp_profile), ret, out);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_DELAY_RESP , cmd, &ptp_profile), ret, out);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_ANNOUNCE , cmd, &ptp_profile), ret, out);          
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_SIGNAL , cmd, &ptp_profile), ret, out);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_MANAGEMENT , cmd, &ptp_profile), ret, out);  
            break;
        }
        case CTC_PTP_DEVICE_P2P_TC:
        {
            SetDsPtpMsgProfile(V, updateResidenceTime_f, &ptp_profile, 1); /*sync*/
            SetDsPtpMsgProfile(V, isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyIngressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyPathDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_SYNC , cmd, &ptp_profile), ret, out);
            
            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, updateResidenceTime_f, &ptp_profile, 1); /*delay_req*/
            SetDsPtpMsgProfile(V, isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyEgressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyPathDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_DELAY_REQ , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, updateResidenceTime_f, &ptp_profile, 1); /*peer delay_req*/
            SetDsPtpMsgProfile(V, isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyEgressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyPathDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, prevDiscardObeyException_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_PDELAY_REQ , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, updateResidenceTime_f, &ptp_profile, 1); /*peer delay_resp*/
            SetDsPtpMsgProfile(V, isCFlexUpdateResidenceTime_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyIngressAsymmetryDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, applyPathDelay_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, prevDiscardObeyException_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1<< SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_PDELAY_RESP , cmd, &ptp_profile), ret, out);

            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            SetDsPtpMsgProfile(V, exceptionToCpu_f, &ptp_profile, 1); /*peer delay_resp_follow_up*/
            SetDsPtpMsgProfile(V, discardPacket_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpHeaderTsFormat_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, ptpIngressTsUseHata_f, &ptp_profile, 1);
            SetDsPtpMsgProfile(V, prevDiscardObeyException_f, &ptp_profile, 1);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_PDELAY_RESP_FOLLOW_UP , cmd, &ptp_profile), ret, out);
            sal_memset(&ptp_profile, 0, sizeof(ds_t));
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_FOLLOW_UP , cmd, &ptp_profile), ret, out);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_DELAY_RESP , cmd, &ptp_profile), ret, out);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_ANNOUNCE , cmd, &ptp_profile), ret, out);          
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_SIGNAL , cmd, &ptp_profile), ret, out);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, 1 << SYS_PTP_CLOCK_ID_OFFSET | CTC_PTP_MSG_TYPE_MANAGEMENT , cmd, &ptp_profile), ret, out);  
            break;
        }
        default:
        {
            ret = CTC_E_INVALID_PARAM;
            goto out;
        }
    }

    return CTC_E_NONE;

out:
    return ret;
}


int32
sys_at_ptp_add_device_clock(uint8 lchip, void* p_clock)
{
    int32 ret = CTC_E_NONE;
    ds_t ptp_profile;
    uint8  index = 0;
    uint32 cmd = 0;
    sys_cpu_reason_info_t   reason_info;
    ctc_ptp_clock_t* clock =(ctc_ptp_clock_t*)p_clock;
    
    for (index = 0; index < CTC_PTP_MSG_TYPE_MAX; index++)
    {
        cmd = DRV_IOR(DsPtpMsgProfile_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, clock->clock_id << SYS_PTP_CLOCK_ID_OFFSET | index, cmd, &ptp_profile), ret, out);
        DRV_SET_FIELD_V(lchip, DsPtpMsgProfile_t, DsPtpMsgProfile_ptpHeaderTsFormat_f, &ptp_profile, 1);
        switch (index)
        {
            case CTC_PTP_MSG_TYPE_PDELAY_REQ:
            case CTC_PTP_MSG_TYPE_PDELAY_RESP:
            case CTC_PTP_MSG_TYPE_PDELAY_RESP_FOLLOW_UP:
                DRV_SET_FIELD_V(lchip, DsPtpMsgProfile_t, DsPtpMsgProfile_prevDiscardObeyException_f, &ptp_profile, 1);
                break;
            default:
                break;
        }
        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_DISCARD))
        {
            DRV_SET_FIELD_V(lchip, DsPtpMsgProfile_t, DsPtpMsgProfile_discardPacket_f, &ptp_profile, 1);
        }

        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_COPY_TO_CPU))
        {
            DRV_SET_FIELD_V(lchip, DsPtpMsgProfile_t, DsPtpMsgProfile_exceptionToCpu_f, &ptp_profile, 1);
            DRV_SET_FIELD_V(lchip, DsPtpMsgProfile_t, DsPtpMsgProfile_ptpIngressTsUseHata_f, &ptp_profile, 1);
            DRV_SET_FIELD_V(lchip, DsPtpMsgProfile_t, DsPtpMsgProfile_exceptionInfoSel_f, &ptp_profile, clock->domain_id);
        }

        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_RESIDENCE_TIME))
        {
            DRV_SET_FIELD_V(lchip, DsPtpMsgProfile_t, DsPtpMsgProfile_updateResidenceTime_f, &ptp_profile, 1);
        }

        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_PATH_DELAY))
        {
            DRV_SET_FIELD_V(lchip, DsPtpMsgProfile_t, DsPtpMsgProfile_applyPathDelay_f, &ptp_profile, 1);
        }

        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_IGS_ASYM_DELAY))
        {
            DRV_SET_FIELD_V(lchip, DsPtpMsgProfile_t, DsPtpMsgProfile_applyIngressAsymmetryDelay_f, &ptp_profile, 1);
        }

        if (CTC_FLAG_ISSET(clock->action_flag[index], CTC_PTP_ACTION_FLAG_EGS_ASYM_DELAY))
        {
            DRV_SET_FIELD_V(lchip, DsPtpMsgProfile_t, DsPtpMsgProfile_applyEgressAsymmetryDelay_f, &ptp_profile, 1);
        }
        
        cmd = DRV_IOW(DsPtpMsgProfile_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, clock->clock_id << SYS_PTP_CLOCK_ID_OFFSET | index, cmd, &ptp_profile));
    }
    if (clock->domain_id == MCHIP_CAP(SYS_CAP_PTP_DOMAIN_1))
    {
        ds_t ds;
        sal_memset(&reason_info, 0, sizeof(sys_cpu_reason_info_t));
        reason_info.reason_id = clock->cpu_reason;
        CTC_ERROR_GOTO(sys_usw_cpu_reason_alloc_exception_index(lchip, CTC_INGRESS, &reason_info), ret, out);

        cmd = DRV_IOR(IpeFwdPtpCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ds), ret, error1);
        SetIpeFwdPtpCtl(V, g_1_exceptionIndex_f, &ds, reason_info.exception_index);
        SetIpeFwdPtpCtl(V, g_1_exceptionSubIndex_f, &ds, reason_info.exception_subIndex);
        cmd = DRV_IOW(IpeFwdPtpCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, 0, cmd, &ds), ret, error1);

        if (p_usw_ptp_master[lchip]->alloced_cpu_reason)
        {
            reason_info.reason_id = p_usw_ptp_master[lchip]->alloced_cpu_reason;
            CTC_ERROR_RETURN(sys_usw_cpu_reason_free_exception_index(lchip, CTC_INGRESS, &reason_info));
        }
        p_usw_ptp_master[lchip]->alloced_cpu_reason = clock->cpu_reason;

    }

    return CTC_E_NONE;
    
error1:
    sys_usw_cpu_reason_free_exception_index(lchip, CTC_INGRESS, &reason_info);

out:
    return ret;
}
int32
sys_at_ptp_remove_device_clock(uint8 lchip, void* p_clock)
{
    int32 ret = CTC_E_NONE;
    ds_t ptp_profile;
    uint32 cmd = 0;
    uint8 index =0;
    ctc_ptp_clock_t* clock = (ctc_ptp_clock_t*)p_clock; 

    sal_memset(&ptp_profile, 0, sizeof(ds_t));

    for (index = 0; index < CTC_PTP_MSG_TYPE_MAX; index++)
    {
        cmd = DRV_IOW(DsPtpMsgProfile_t, DRV_ENTRY_FLAG);
        CTC_ERROR_GOTO(DRV_IOCTL(lchip, clock->clock_id<< SYS_PTP_CLOCK_ID_OFFSET | index, cmd, &ptp_profile), ret, out);
    }

    if (clock->domain_id == MCHIP_CAP(SYS_CAP_PTP_DOMAIN_1))
    {
        sys_cpu_reason_info_t   reason_info;
        sal_memset(&reason_info, 0, sizeof(sys_cpu_reason_info_t));
        reason_info.reason_id = p_usw_ptp_master[lchip]->alloced_cpu_reason;
        CTC_ERROR_RETURN(sys_usw_cpu_reason_free_exception_index(lchip, CTC_INGRESS, &reason_info));
        p_usw_ptp_master[lchip]->alloced_cpu_reason =0;
    }

    return CTC_E_NONE;

    out:
    return ret;
}

int32 sys_at_ptp_set_adjust_delay(uint8 lchip, uint32 gport, uint8 type, int64 value)
{

    int32 ret = CTC_E_NONE;
    uint32 cmd = 0;
    uint8 negtive = 0;
    uint32 chan_id = 0;
    uint32 tmp_value=0;
    uint32 result_data=0;
    sys_usw_dmps_port_info_t dmps_port_info = {0};
    DsDestChannel_m dest_channel;
    DsSrcChannel_m src_channel;

    dmps_port_info.gport = gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
    if (!SYS_IS_NETWORK_CHANNEL(chan_id))
    {
        return CTC_E_INVALID_PARAM;
    }

    switch (type)
    {
        case CTC_PTP_ADJUST_DELAY_INGRESS_LATENCY:
        {
            cmd = DRV_IOR(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);
            SetDsSrcChannel(V, latencyAdj1Value_f, &src_channel, value & 0xFFFFLL);/*IngressLatency*/

            tmp_value = GetDsSrcChannel(V, latencyAdj2Value_f, &src_channel);            
            negtive = GetDsSrcChannel(V, latencyAdj2Negtive_f, &src_channel);
            result_data = _sys_at_ptp_get_delay(value & 0xFFFFLL, tmp_value, &negtive);
            SetDsSrcChannel(V, latencyAdj3Value_f, &src_channel, result_data & 0xFFFFFLL);/* IngressLantency + AsymmetryDelay*/
            SetDsSrcChannel(V, latencyAdj3Negtive_f, &src_channel, negtive);

            negtive =0;
            tmp_value = GetDsSrcChannel(V, latencyAdj4Value_f, &src_channel);
            SetDsSrcChannel(V, latencyAdj5Value_f, &src_channel, (tmp_value + (value & 0xFFFFLL)) & 0x3FFFFFFFLL);/* IngressLantency + PathDelay*/
            SetDsSrcChannel(V, latencyAdj5Negtive_f, &src_channel, negtive);

            tmp_value = GetDsSrcChannel(V, latencyAdj6Value_f, &src_channel);            
            negtive = GetDsSrcChannel(V, latencyAdj6Negtive_f, &src_channel);
            result_data = _sys_at_ptp_get_delay(value & 0xFFFFLL, tmp_value, &negtive);
            SetDsSrcChannel(V, latencyAdj7Value_f, &src_channel, result_data & 0x3FFFFFFFLL);/* IngressLantency + AsymmetryDelay + PathDelay*/
            SetDsSrcChannel(V, latencyAdj7Negtive_f, &src_channel, negtive);
      
            cmd = DRV_IOW(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);

            break;
        }
        case CTC_PTP_ADJUST_DELAY_EGRESS_LATENCY:
        {
            cmd = DRV_IOR(DsDestChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &dest_channel), ret, out);

            SetDsDestChannel(V, egressLatency_f, &dest_channel, value & 0xFFFFLL);
            cmd = DRV_IOW(DsDestChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &dest_channel), ret, out);

            break;
        }
        case CTC_PTP_ADJUST_DELAY_INGRESS_ASYMMETRY:
        {
            negtive = (value >= 0) ? 0 : 1;
            if (value < 0)
            {
                value = -value;
            }
            value = value&0xFFFFFLL;

            cmd = DRV_IOR(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);
            SetDsSrcChannel(V, latencyAdj2Value_f, &src_channel, value);/*AsymmetryDelay*/
            SetDsSrcChannel(V, latencyAdj2Negtive_f, &src_channel, negtive);

            tmp_value = GetDsSrcChannel(V, latencyAdj1Value_f, &src_channel);   
            result_data = _sys_at_ptp_get_delay(tmp_value, value, &negtive);
            SetDsSrcChannel(V, latencyAdj3Value_f, &src_channel, result_data & 0xFFFFFLL);/* IngressLantency + AsymmetryDelay*/
            SetDsSrcChannel(V, latencyAdj3Negtive_f, &src_channel, negtive);

            tmp_value = GetDsSrcChannel(V, latencyAdj4Value_f, &src_channel);   
            result_data = _sys_at_ptp_get_delay(tmp_value, value, &negtive);
            SetDsSrcChannel(V, latencyAdj6Value_f, &src_channel, result_data & 0x3FFFFFFFLL);/* PathDelay + AsymmetryDelay*/
            SetDsSrcChannel(V, latencyAdj6Negtive_f, &src_channel, negtive);

            tmp_value = GetDsSrcChannel(V, latencyAdj5Value_f, &src_channel);            
            result_data = _sys_at_ptp_get_delay(tmp_value, value, &negtive);
            SetDsSrcChannel(V, latencyAdj7Value_f, &src_channel, result_data & 0x3FFFFFFFLL);/* IngressLantency + AsymmetryDelay + PathDelay*/
            SetDsSrcChannel(V, latencyAdj7Negtive_f, &src_channel, negtive);

            cmd = DRV_IOW(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);

            break;
        }
        case CTC_PTP_ADJUST_DELAY_EGRESS_ASYMMETRY:
        {
            negtive = (value >= 0) ? 0 : 1;
            if (value < 0)
            {
                value = -value;
            }

            cmd = DRV_IOR(DsDestChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &dest_channel), ret, out);

            SetDsDestChannel(V, asymmetryDelayNegtive_f, &dest_channel, negtive);
            SetDsDestChannel(V, asymmetryDelay_f, &dest_channel, value & 0xFFFFFLL);
            cmd = DRV_IOW(DsDestChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &dest_channel), ret, out);

            break;
        }
        case CTC_PTP_ADJUST_DELAY_PATH_DELAY:
        {

            cmd = DRV_IOR(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);
            SetDsSrcChannel(V, latencyAdj4Value_f, &src_channel, value & 0x3FFFFFFFLL);/*PathDelay*/

            tmp_value = GetDsSrcChannel(V, latencyAdj2Value_f, &src_channel);            
            negtive = GetDsSrcChannel(V, latencyAdj2Negtive_f, &src_channel);
            result_data = _sys_at_ptp_get_delay(value & 0xFFFFLL, tmp_value, &negtive);
            SetDsSrcChannel(V, latencyAdj6Value_f, &src_channel, result_data & 0x3FFFFFFFLL);/* PathDelay + AsymmetryDelay*/
            SetDsSrcChannel(V, latencyAdj6Negtive_f, &src_channel, negtive);
            
            negtive = 0;
            tmp_value = GetDsSrcChannel(V, latencyAdj1Value_f, &src_channel);
            SetDsSrcChannel(V, latencyAdj5Value_f, &src_channel, (tmp_value + (value & 0xFFFFLL)) & 0x3FFFFFFFLL);/* IngressLantency + PathDelay*/
            SetDsSrcChannel(V, latencyAdj5Negtive_f, &src_channel, negtive);
            
            tmp_value = GetDsSrcChannel(V, latencyAdj3Value_f, &src_channel);            
            negtive = GetDsSrcChannel(V, latencyAdj3Negtive_f, &src_channel);
            result_data = _sys_at_ptp_get_delay(value & 0xFFFFLL, tmp_value, &negtive);
            SetDsSrcChannel(V, latencyAdj7Value_f, &src_channel, result_data & 0x3FFFFFFFLL);/* IngressLantency + AsymmetryDelay + PathDelay*/
            SetDsSrcChannel(V, latencyAdj7Negtive_f, &src_channel, negtive);
            
            cmd = DRV_IOW(DsSrcChannel_t, DRV_ENTRY_FLAG);
            CTC_ERROR_GOTO(DRV_IOCTL(lchip, chan_id, cmd, &src_channel), ret, out);

            break;
        }
        default:
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    return CTC_E_NONE;

  out:
    return ret;
}

STATIC int32 _sys_at_ptp_get_session_id(uint8 lchip, uint32 gport,uint8* session_id, uint8* domain_id)
{
    uint8 index = 0;
    uint8 domain_index = 0;
    for (domain_index = 0; domain_index <= MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID); domain_index++)
    {
        for (index = 0; index <= MCHIP_CAP(SYS_CAP_PTP_MAX_SESSION_ID); index++)
        {
            if (CTC_IS_BIT_SET(p_usw_ptp_master[lchip]->session_en_bmp[domain_index], index)
                && gport == p_usw_ptp_master[lchip]->session[domain_index*SYS_PTP_SESSION_NUM_PER_DOMAIN + index].gport)
            {
                *session_id = index;
                *domain_id = domain_index;
                return CTC_E_NONE;
            }
        }
    }
    return CTC_E_NOT_EXIST;
}

int32
sys_at_ptp_add_session(uint8 lchip, void* session_cfg)
{
#if defined E_UNIT && (FEATURE_MODE == 0)
    int32 ret=0;
    ctc_ptp_session_t* p_session = (ctc_ptp_session_t*)session_cfg;
    sys_eunit_ptp_cfg_t sys_session_cfg;
    sys_nh_info_dsnh_t nhinfo;
    sys_usw_opf_t opf;
    uint32 offset =0;
    uint8 session_id =0;
    uint32 speed =0;
    uint32 mac_id = 0;
    uint8 domain_id =0;
    sys_intr_type_t type;
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    CTC_ERROR_RETURN(_sys_at_ptp_session_param_check(lchip, p_session));

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    sal_memset(&sys_session_cfg, 0, sizeof(sys_eunit_ptp_cfg_t));
    sal_memset(&type, 0, sizeof(type));

    opf.pool_type = p_usw_ptp_master[lchip]->ptp_opf_type;
    opf.pool_index = p_session->domain_id;
    ret = _sys_at_ptp_get_session_id(lchip, p_session->gport, &session_id, &domain_id);
    if ( ret == CTC_E_NOT_EXIST)
    {
        CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(lchip, &opf, 1, &offset));
    }
    else
    {
        offset = session_id;
    }

    sal_memset(&nhinfo, 0, sizeof(sys_nh_info_dsnh_t));
    CTC_ERROR_GOTO(sys_usw_nh_get_nhinfo(lchip, p_session->nhid1, &nhinfo, 0),ret,error1);
    sys_session_cfg.event_destmap = nhinfo.dest_map;
    sys_session_cfg.event_nh_ptr = nhinfo.dsnh_offset;

    sal_memset(&nhinfo, 0, sizeof(sys_nh_info_dsnh_t));
    CTC_ERROR_GOTO(sys_usw_nh_get_nhinfo(lchip, p_session->nhid2, &nhinfo, 0),ret,error1);
    sys_session_cfg.general_destmap = nhinfo.dest_map;
    sys_session_cfg.general_nh_ptr = nhinfo.dsnh_offset;

    dmps_port_info.gport = p_session->gport;
    CTC_ERROR_GOTO(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, &mac_id),ret,error1);
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_SPEED_VALUE, &speed));/*return value is Mbps*/

    sys_session_cfg.param_valid = 1;
    sys_session_cfg.session_enable = 1;
    sys_session_cfg.session_id = offset;
    sys_session_cfg.domain_id = p_session->domain_id;

    sys_session_cfg.parent_port_num = p_session->parent_info.parent_port_num;

    sys_session_cfg.tx_en = p_session->tx_en;
    sys_session_cfg.rx_en = p_session->rx_en;
    sys_session_cfg.report_msg_en = p_session->report_msg_en;
    sys_session_cfg.report_ts_en = p_session->report_ts_en;
    sys_session_cfg.ext_len = p_session->ext_len;
    sys_session_cfg.domain_num = p_session->default_info.domain_number;
    sys_session_cfg.is_two_step = p_session->default_info.two_step_flag;

    sys_session_cfg.delay_req_interval = p_session->port_info.delay_req_interval;
    sys_session_cfg.pdelay_req_interval = p_session->port_info.pdelay_req_interval;
    sys_session_cfg.source_port_id = p_session->port_info.source_port_id;
    sys_session_cfg.sync_interval = p_session->port_info.sync_interval;
    sys_session_cfg.version_id = p_session->port_info.version_id;    

    sys_session_cfg.speed = speed;
    sys_session_cfg.mac_id = mac_id;
    sys_session_cfg.lport = CTC_MAP_GPORT_TO_LPORT(p_session->gport);

    sal_memcpy(sys_session_cfg.clock_identity,p_session->default_info.clock_identity,sizeof(sys_session_cfg.clock_identity));
    sal_memcpy(sys_session_cfg.parent_clock_id,p_session->parent_info.parent_identity,sizeof(sys_session_cfg.clock_identity));

    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->set_cfg)
    {
        type.intr = SYS_INTR_FUNC_PTP_TX_TS_FIFO_0_START + mac_id/SYS_PTP_MAC_NUM_PER_MCMAC;
        type.sub_intr = INVG;
        CTC_ERROR_RETURN(sys_usw_interrupt_set_en(lchip, &type, 0));
        type.intr = SYS_INTR_FUNC_PTP_TX_TS_FIFO_1_START + mac_id/SYS_PTP_MAC_NUM_PER_MCMAC;
        CTC_ERROR_RETURN(sys_usw_interrupt_set_en(lchip, &type, 0));
        CTC_ERROR_GOTO(MCHIP_EUNIT(lchip)->set_cfg(lchip, sys_session_cfg.domain_id? SYS_EUNIT_CFG_PTP_DOMAIN_1 : SYS_EUNIT_CFG_PTP_DOMAIN_0, (void*)&sys_session_cfg),ret,error1);
    }

    session_id = offset + p_session->domain_id * SYS_PTP_SESSION_NUM_PER_DOMAIN;
    p_usw_ptp_master[lchip]->session[session_id].gport = p_session->gport;
    CTC_BIT_SET(p_usw_ptp_master[lchip]->session_en_bmp[p_session->domain_id],offset);
    p_usw_ptp_master[lchip]->session[session_id].nhid1 = p_session->nhid1;
    p_usw_ptp_master[lchip]->session[session_id].nhid2 = p_session->nhid2;

    goto RETURN;
    
   error1:
       sys_usw_opf_free_offset(lchip, &opf, 1, offset);

   RETURN:
    return ret;
#else
    return CTC_E_NONE;
#endif
}


int32
sys_at_ptp_remove_session(uint8 lchip, void* session_cfg)
{
#if defined E_UNIT && (FEATURE_MODE == 0)

    uint8 session_id = 0;
    uint8 domain_id =0;
    uint8 domain_index = 0;
    uint8 index = 0;
    uint8 need_register = 1;
    uint32 old_mcmac_id = 0;
    uint32 mac_id = 0;
    sys_eunit_ptp_cfg_t sys_session_cfg;
    sys_usw_opf_t opf;
    ctc_ptp_session_t* p_session = (ctc_ptp_session_t*)session_cfg;
    sys_usw_dmps_port_info_t dmps_port_info;
    sys_intr_type_t type;

    sal_memset(&sys_session_cfg, 0, sizeof(sys_eunit_ptp_cfg_t));
    sal_memset(&dmps_port_info, 0, sizeof(sys_usw_dmps_port_info_t));
    sal_memset(&type, 0, sizeof(type));

    if (_sys_at_ptp_get_session_id(lchip, p_session->gport, &session_id,&domain_id) == CTC_E_NOT_EXIST)
    {
        return CTC_E_NOT_EXIST;
    }

    sys_session_cfg.param_valid = 1;
    sys_session_cfg.domain_id = domain_id;
    sys_session_cfg.session_id = session_id;
    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->set_cfg)
    {
        CTC_ERROR_RETURN(MCHIP_EUNIT(lchip)->set_cfg(lchip, domain_id? SYS_EUNIT_CFG_PTP_DOMAIN_1 : SYS_EUNIT_CFG_PTP_DOMAIN_0, (void*)&sys_session_cfg));
    }

    dmps_port_info.gport = p_session->gport;
    CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, &old_mcmac_id));
    old_mcmac_id /= SYS_PTP_MAC_NUM_PER_MCMAC;
    
    /*remove session port */
    p_usw_ptp_master[lchip]->session[domain_id*SYS_PTP_SESSION_NUM_PER_DOMAIN + session_id].gport = 0;
    CTC_BIT_UNSET(p_usw_ptp_master[lchip]->session_en_bmp[domain_id], session_id);
    p_usw_ptp_master[lchip]->session[domain_id*SYS_PTP_SESSION_NUM_PER_DOMAIN + session_id].nhid1 = 0;
    p_usw_ptp_master[lchip]->session[domain_id*SYS_PTP_SESSION_NUM_PER_DOMAIN + session_id].nhid2 = 0;

    /*find session port in same McMac*/
    for (domain_index = 0; domain_index <= MCHIP_CAP(SYS_CAP_PTP_MAX_DOMAIN_ID); domain_index++)
    {
        for (index = 0; index <= MCHIP_CAP(SYS_CAP_PTP_MAX_SESSION_ID); index++)
        {
            if (CTC_IS_BIT_SET(p_usw_ptp_master[lchip]->session_en_bmp[domain_index], index))
            {
                dmps_port_info.gport = p_usw_ptp_master[lchip]->session[domain_index*SYS_PTP_SESSION_NUM_PER_DOMAIN + index].gport;
                CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_MAC_ID, &mac_id));
                if (old_mcmac_id == (mac_id/SYS_PTP_MAC_NUM_PER_MCMAC))
                {
                    need_register = 0;
                    break;
                }
            }
        }
    }

    if(need_register)
    {
        type.intr = SYS_INTR_FUNC_PTP_TX_TS_FIFO_0_START + mac_id/SYS_PTP_MAC_NUM_PER_MCMAC;
        type.sub_intr = INVG;
        CTC_ERROR_RETURN(sys_usw_interrupt_set_en(lchip, &type, 1));
        type.intr = SYS_INTR_FUNC_PTP_TX_TS_FIFO_1_START + mac_id/SYS_PTP_MAC_NUM_PER_MCMAC;
        CTC_ERROR_RETURN(sys_usw_interrupt_set_en(lchip, &type, 1));
    }

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type = p_usw_ptp_master[lchip]->ptp_opf_type;
    opf.pool_index = domain_id;
    sys_usw_opf_free_offset(lchip, &opf, 1, session_id); 
#endif
    return CTC_E_NONE;
}

int32
sys_at_ptp_get_session(uint8 lchip, void* session_cfg)
{
#if defined E_UNIT && (FEATURE_MODE == 0)
    sys_eunit_ptp_cfg_t sys_session_cfg;
    ctc_ptp_session_t* p_session = (ctc_ptp_session_t*)session_cfg;
    uint8 gchip = 0;
    uint8 session_id = 0;
    uint8 domain_id = 0;
    
    sal_memset(&sys_session_cfg, 0, sizeof(sys_eunit_ptp_cfg_t));
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));

    if (_sys_at_ptp_get_session_id(lchip, p_session->gport, &session_id,&domain_id) == CTC_E_NOT_EXIST)
    {
        return CTC_E_NOT_EXIST;
    }

    sys_session_cfg.domain_id = domain_id;
    sys_session_cfg.session_id = session_id;

    if (MCHIP_EUNIT(lchip) && MCHIP_EUNIT(lchip)->get_cfg)
    {
        CTC_ERROR_RETURN(MCHIP_EUNIT(lchip)->get_cfg(lchip, domain_id? SYS_EUNIT_CFG_PTP_DOMAIN_1 : SYS_EUNIT_CFG_PTP_DOMAIN_0, (void*)&sys_session_cfg));
    }

    p_session->domain_id = sys_session_cfg.domain_id;
    p_session->tx_en = sys_session_cfg.tx_en;
    p_session->rx_en = sys_session_cfg.rx_en;
    p_session->report_msg_en = sys_session_cfg.report_msg_en;
    p_session->report_ts_en = sys_session_cfg.report_ts_en;
    p_session->ext_len = sys_session_cfg.ext_len;

    p_session->default_info.domain_number = sys_session_cfg.domain_num;
    p_session->default_info.two_step_flag = sys_session_cfg.is_two_step;
    p_session->parent_info.parent_port_num = sys_session_cfg.parent_port_num;

    p_session->port_info.delay_req_interval = sys_session_cfg.delay_req_interval;
    p_session->port_info.pdelay_req_interval = sys_session_cfg.pdelay_req_interval;
    p_session->port_info.source_port_id = sys_session_cfg.source_port_id;
    p_session->port_info.sync_interval = sys_session_cfg.sync_interval;
    p_session->port_info.version_id = sys_session_cfg.version_id;    
    p_session->nhid1 = p_usw_ptp_master[lchip]->session[domain_id*SYS_PTP_SESSION_NUM_PER_DOMAIN + session_id].nhid1;
    p_session->nhid2 = p_usw_ptp_master[lchip]->session[domain_id*SYS_PTP_SESSION_NUM_PER_DOMAIN + session_id].nhid2;

    sal_memcpy(p_session->parent_info.parent_identity,sys_session_cfg.parent_clock_id,sizeof(sys_session_cfg.clock_identity));
    sal_memcpy(p_session->default_info.clock_identity,sys_session_cfg.clock_identity,sizeof(sys_session_cfg.clock_identity));
    sal_memcpy(p_session->tx_stats,sys_session_cfg.tx_stats,sizeof(uint32)*CTC_PTP_MSG_TYPE_MAX);
    sal_memcpy(p_session->rx_stats,sys_session_cfg.rx_stats,sizeof(uint32)*CTC_PTP_MSG_TYPE_MAX);
    sal_memcpy(p_session->drop_stats,sys_session_cfg.drop_stats,sizeof(uint32)*CTC_PTP_MSG_TYPE_MAX);

#endif

    return CTC_E_NONE;
}

int32
sys_at_ptp_get_clock_timestamp(uint8 lchip, void* p_timestamp)
{
    uint16 ts_rc_id = 0;
    uint32 cmd = 0;
    ds_t ds;
    uint32 ts_buf[2]={0};
    uint8 mask =0x3F;
    ctc_ptp_time_t *time_stamp = (ctc_ptp_time_t*)p_timestamp;

    ts_rc_id = _sys_at_ptp_get_top_ts_rc_id(time_stamp->domain_id);

    /*Set shadow mask and capture mode*/
    cmd = DRV_IOR(TsRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_rc_id , DRV_CMD_PP_EN(cmd), &ds));
    CTC_BIT_UNSET(mask, SYS_PTP_SHADOW_LOCAL_TS); 
    SetTsRcCtl(V, syncModeMask_f, &ds, mask);

    cmd = DRV_IOW(TsRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_rc_id , DRV_CMD_PP_EN(cmd), &ds));

    /*Trigger Capture operation*/
    cmd = DRV_IOR(TsRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_rc_id , DRV_CMD_PP_EN(cmd), &ds));
    SetTsRcCtl(V, captureManualTrigger_f, &ds, 1);
    cmd = DRV_IOW(TsRcCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_rc_id , DRV_CMD_PP_EN(cmd), &ds));

    /*Read Captured timestamp*/
    cmd = DRV_IOR(TsRcLocalTsShadow_t, DRV_ENTRY_FLAG);/* syncModeMask[SYS_PTP_SHADOW_LOCAL_TS]should be clean*/
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, ts_rc_id , DRV_CMD_PP_EN(cmd), &ds));
    GetTsRcLocalTsShadow(A, localTsShadow_f, &ds, ts_buf);

    time_stamp->seconds =  ts_buf[1];
    time_stamp->nanoseconds =  ts_buf[0]>>2;
    time_stamp->nano_nanoseconds =  (ts_buf[0]&0x3)*MCHIP_CAP(SYS_CAP_PTP_NS_OR_NNS_VALUE)/4;

    return CTC_E_NONE;
}

int32
sys_at_ptp_init(uint8 lchip, void* ptp_global_cfg)
{
    int32 ret = 0;
    sys_usw_opf_t opf;

     /* init session */
     p_usw_ptp_master[lchip]->session = (sys_ptp_session_t*)mem_malloc(MEM_PTP_MODULE, sizeof(sys_ptp_session_t)*SYS_PTP_MAX_SESSION_NUM);
     if (NULL == p_usw_ptp_master[lchip]->session)
     {
         SYS_PTP_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
         ret = CTC_E_NO_MEMORY;
         goto error_return;
     }

    sal_memset(p_usw_ptp_master[lchip]->session, 0, sizeof(sys_ptp_session_t)*SYS_PTP_MAX_SESSION_NUM);

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    CTC_ERROR_GOTO(sys_usw_opf_init(lchip, &p_usw_ptp_master[lchip]->ptp_opf_type, 2, "opf-ptp-session"),ret,error_return1);
    opf.pool_type = p_usw_ptp_master[lchip]->ptp_opf_type;
    opf.pool_index = 0;    
    CTC_ERROR_GOTO(sys_usw_opf_init_offset(lchip, &opf, 0, SYS_PTP_SESSION_NUM_PER_DOMAIN),ret,error_return2);
    opf.pool_index = 1;    
    CTC_ERROR_GOTO(sys_usw_opf_init_offset(lchip, &opf, 0, SYS_PTP_SESSION_NUM_PER_DOMAIN),ret,error_return2);

#if defined E_UNIT && (FEATURE_MODE == 0)
    sys_usw_eunit_regitser_isr(lchip, SYS_EUNIT_ISR_PTP, sys_at_ptp_isr);
    CTC_ERROR_GOTO(sys_usw_interrupt_register_event_cb(lchip, CTC_EVENT_PTP_SLAVE_TS_READY, sys_at_ptp_event_cb),ret,error_return2);
#endif
    return CTC_E_NONE;

error_return2:
    sys_usw_opf_deinit(lchip, p_usw_ptp_master[lchip]->ptp_opf_type);
error_return1:
    mem_free(p_usw_ptp_master[lchip]->session);
    p_usw_ptp_master[lchip]->session = NULL;
error_return:
    return ret;
}

#endif
#endif


